package gui;

import java.util.GregorianCalendar;

import msjcalendar.Event;
import msjcalendar.RepeatingEvent;
import msjcalendar.SingleEvent;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.graphics.Color;

import enums.StatusEnum;

/**
 * @author Markus
 * 
 * Composite for edit a new or existing event.
 *
 */
public class EventComposite extends Composite {
	
	/**
	 * Label for Log.
	 */
	private Label outputLabel;
	/**
	 * Label for Event-Subject.
	 */
	private Label subjectLabel;
	/**
	 * Input-Field for Event-Subject.
	 */
	private Text subjectText;
	/**
	 * Label for Event-Description.
	 */
	private Label descriptionLabel;
	/**
	 * Input-Field for Event-Description.
	 */
	private Text descriptionText;
	/**
	 * Label for Event-Place.
	 */
	private Label placeLabel;
	/**
	 * Input-Field for Event-Place.
	 */
	private Text placeText;
	/**
	 * Button starts Edit-Mode.
	 */
	private Button editButton;
	/**
	 * Button closes the Event-Dialog. 
	 */
	private Button closeButton;
	/**
	 * Button deletes an selected Event.
	 */
	private Button deleteButton;
	/**
	 * Label for Event-Begin.
	 */
	private Label beginLabel;
	/**
	 * Label for Event-End.
	 */
	private Label endLabel;
	/**
	 * Label for Event-Status.
	 */
	private Label statusLabel;
	/**
	 * Label for All-Day-Event. 
	 */
	private Label allDayLabel;
	/**
	 * Combo for choose Event-Status.
	 */
	private Combo statusCombo;
	/**
	 * Button changes a Event to an All-Day-Event.
	 */
	private Button allDayButton;
	
	/**
	 * Label for repeating-Event.
	 */
	private Label repeatingEventLabel;
	
	/**
	 * Button changes a Single-Event to a repeating-Event.
	 */
	private Button repeatingEventCheckbox;
	
	/**
	 * Button cancels editing or creating an Event.
	 */
	private Button cancelButton;
	
	/**
	 * Button saves an Event which is edit or create.
	 */
	private Button confirmButton;
	
	/**
	 * composite for repeating events.
	 */
	private PatternComposite patternComposite;
	/**
	 * begin of new event.
	 */
	private DateTimeComposite beginDateTime;
	/**
	 * end of new event.
	 */
	private DateTimeComposite endDateTime;
	/**
	 * new event.
	 */
	private Event event;
	
	/*-----------------------------------------------------------------------------------*/
	
	/**
	 * @param parent parent control
	 * @param style SWT-style
	 */
	public EventComposite(final Composite parent, final int style) {
		super(parent, style);
		FormLayout layout = new FormLayout();
		this.setLayout(layout);
		
		this.editButton = new Button(this, SWT.PUSH);
		editButton.setText("Edit");
		FormData data = new FormData();
		data.top = new FormAttachment(0, 5);
		data.right = new FormAttachment(100, 0);
		editButton.setLayoutData(data);
		
		this.closeButton = new Button(this, SWT.PUSH);
		closeButton.setText("Close");
		data = new FormData();
		data.top = new FormAttachment(0, 5);
		data.left = new FormAttachment(0, 5);
		closeButton.setLayoutData(data);
		
		this.deleteButton = new Button(this, SWT.PUSH);
		deleteButton.setText("Delete");
		data = new FormData();
		data.top = new FormAttachment(0, 5);
		data.right = new FormAttachment(editButton);
		deleteButton.setLayoutData(data);
		
		this.subjectLabel = new Label(this, SWT.LEFT);
		data = new FormData();
		data.top = new FormAttachment(editButton, 7);
		data.left = new FormAttachment(0, 0);
		subjectLabel.setLayoutData(data);
		subjectLabel.setText("Subject:");
		
		this.subjectText = new Text(this, SWT.SINGLE | SWT.RIGHT | SWT.BORDER);
		data = new FormData();
		data.top = new FormAttachment(editButton, 5);
		data.left = new FormAttachment(subjectLabel, 40);
		data.right = new FormAttachment(100, 0);
		subjectText.setLayoutData(data);
		
		this.descriptionLabel = new Label(this, SWT.LEFT);
		data = new FormData();
		data.top = new FormAttachment(subjectText, 7);
		data.left = new FormAttachment(0, 0);
		descriptionLabel.setLayoutData(data);
		descriptionLabel.setText("Description:");
		
		this.descriptionText = new Text(this, SWT.SINGLE | SWT.RIGHT | SWT.BORDER);
		data = new FormData();
		data.top = new FormAttachment(subjectText, 5);
		data.left = new FormAttachment(subjectLabel, 40);
		data.right = new FormAttachment(100, 0);
		descriptionText.setLayoutData(data);
		
		this.placeLabel = new Label(this, SWT.LEFT);
		data = new FormData();
		data.top = new FormAttachment(descriptionText, 7);
		data.left = new FormAttachment(0, 0);
		placeLabel.setLayoutData(data);
		placeLabel.setText("Place:");
		
		this.placeText = new Text(this, SWT.SINGLE | SWT.RIGHT | SWT.BORDER);
		data = new FormData();
		data.top = new FormAttachment(descriptionText, 5);
		data.left = new FormAttachment(subjectLabel, 40);
		data.right = new FormAttachment(100, 0);
		placeText.setLayoutData(data);
		
		this.beginLabel = new Label(this, SWT.LEFT);
		data = new FormData();
		data.top = new FormAttachment(placeText, 7);
		data.left = new FormAttachment(0, 0);
		beginLabel.setLayoutData(data);
		beginLabel.setText("Begin:");
		
		this.beginDateTime = new DateTimeComposite(this, SWT.NONE);
		data = new FormData();
		data.top = new FormAttachment(placeText, 5);
		data.right = new FormAttachment(100, 0);
		beginDateTime.setLayoutData(data);
		GregorianCalendar now = new GregorianCalendar();
		this.beginDateTime.setCalendar(now);
		this.beginDateTime.addListener(SWT.Modify, new Listener() {
			
			@Override
			public void handleEvent(final org.eclipse.swt.widgets.Event arg0) {
				if (endDateTime.getCalendar().before(beginDateTime.getCalendar())) {
					endDateTime.setCalendar(beginDateTime.getCalendar());
				}
			}
		});
		
		this.endLabel = new Label(this, SWT.LEFT);
		data = new FormData();
		data.top = new FormAttachment(beginDateTime, 7);
		data.left = new FormAttachment(0, 0);
		endLabel.setLayoutData(data);
		endLabel.setText("End:");
		
		this.endDateTime = new DateTimeComposite(this, SWT.NONE);
		data = new FormData();
		data.top = new FormAttachment(beginDateTime, 5);
		data.right = new FormAttachment(100, 0);
		endDateTime.setLayoutData(data);
		endDateTime.setCalendar(now);
		
		this.statusLabel = new Label(this, SWT.LEFT);
		data = new FormData();
		data.top = new FormAttachment(endDateTime, 7);
		data.left = new FormAttachment(0, 0);
		statusLabel.setLayoutData(data);
		statusLabel.setText("Status:");
		
		this.statusCombo = new Combo(this, SWT.READ_ONLY | SWT.VERTICAL | SWT.BORDER);
		data = new FormData();
		data.top = new FormAttachment(endDateTime, 5);
		data.right = new FormAttachment(100, 0);
		statusCombo.setLayoutData(data);
		for (StatusEnum s: StatusEnum.values()) {
			statusCombo.add(s.toString());
		}
		statusCombo.setText("BUSY");
		this.allDayLabel = new Label(this, SWT.LEFT);
		data = new FormData();
		data.top = new FormAttachment(statusCombo, 7);
		data.left = new FormAttachment(0, 0);
		this.allDayLabel.setLayoutData(data);
		this.allDayLabel.setText("All Day:");
		this.allDayButton = new Button(this, SWT.CHECK);
		data = new FormData();
		data.top = new FormAttachment(statusCombo, 5);
		data.right = new FormAttachment(100, 0);
		allDayButton.setLayoutData(data);
		allDayButton.addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(final SelectionEvent arg0) {
				if (allDayButton.getSelection()) {
					beginDateTime.setTimeEnabled(false);
					endDateTime.setTimeEnabled(false);
				} else {
					beginDateTime.setTimeEnabled(true);
					endDateTime.setTimeEnabled(true);
				}		
			}
			@Override
			public void widgetDefaultSelected(final SelectionEvent arg0) {
			}
		});
		this.repeatingEventLabel = new Label(this, SWT.LEFT);
		data = new FormData();
		data.top = new FormAttachment(allDayButton, 7);
		data.left = new FormAttachment(0, 0);
		this.repeatingEventLabel.setLayoutData(data);
		this.repeatingEventLabel.setText("Repeating Event:");
		this.repeatingEventCheckbox = new Button(this, SWT.CHECK);
		data = new FormData();
		data.top = new FormAttachment(allDayButton, 5);
		data.right = new FormAttachment(100, 0);
		repeatingEventCheckbox.setLayoutData(data);
		repeatingEventCheckbox.addSelectionListener(new SelectionListener() {
			@Override
			public void widgetSelected(final SelectionEvent arg0) {
				if (repeatingEventCheckbox.getSelection()) {
					patternComposite.setEnabled(true);
					patternComposite.setVisible(true);
				} else {
					patternComposite.setEnabled(false);
					patternComposite.setVisible(false);
				}
			}
			@Override
			public void widgetDefaultSelected(final SelectionEvent arg0) {
				// TODO Auto-generated method stub
				
			}
		});
		
		this.confirmButton = new Button(this, SWT.PUSH);
		data = new FormData();
		data.bottom = new FormAttachment(100, 0);
		data.right = new FormAttachment(100, 0);
		confirmButton.setLayoutData(data);
		this.confirmButton.setText("Confirm");
		this.confirmButton.setVisible(false);
		
		this.cancelButton = new Button(this, SWT.PUSH);
		data = new FormData();
		data.bottom = new FormAttachment(100, 0);
		data.right = new FormAttachment(this.confirmButton, 0);
		cancelButton.setLayoutData(data);
		this.cancelButton.setText("Cancel");
		this.cancelButton.setVisible(false);
		
		this.patternComposite = new PatternComposite(this, SWT.NONE);
		data = new FormData();
		data.top = new FormAttachment(this.repeatingEventCheckbox, 5);
		data.left = new FormAttachment(0, 0);
		data.right = new FormAttachment(100, 0);
		this.patternComposite.setLayoutData(data);
		
		this.outputLabel = new Label(this, SWT.WRAP);
		this.outputLabel.setText(" ");
		this.outputLabel.setForeground(new Color(null, 255, 0, 0));
		data = new FormData();
		data.top = new FormAttachment(this.patternComposite, 5);
		data.left = new FormAttachment(0, 0);
		data.right = new FormAttachment(100, 0);
		data.bottom = new FormAttachment(this.confirmButton, -5);
		this.outputLabel.setLayoutData(data);
		
		this.editButton.addSelectionListener(new SelectionAdapter() {
			
			@Override
			public void widgetSelected(final SelectionEvent e) {
				startEditMode();
			}
		});
		
		cancelButton.addSelectionListener(new SelectionListener() {

			@Override
			public void widgetDefaultSelected(final SelectionEvent arg0) {
			}
			@Override
			public void widgetSelected(final SelectionEvent arg0) {
				endEditMode();
			}
		});
		
		subjectText.setEditable(false);
		descriptionText.setEditable(false);
		placeText.setEditable(false);
		beginDateTime.setEnabled(false);
		endDateTime.setEnabled(false);
		statusCombo.setEnabled(false);
		allDayButton.setEnabled(false);
		repeatingEventCheckbox.setEnabled(false);
		patternComposite.setEnabled(false);
		patternComposite.setVisible(false);
	}
	
	/**
	 * @return the closeButton
	 */
	public Button getCloseButton() {
		return closeButton;
	}

	/**
	 * @return the confirm button
	 */
	public Button getConfirmButton() {
		return this.confirmButton;
	}
	
	/**
	 * @return the cancel button
	 */
	public Button getCancelButton() {
		return this.cancelButton;
	}
	
	/**
	 * @return the delete Button
	 */
	public Button getDeleteButton() {
		return this.deleteButton;
	}
	
	/**
	 * @return the event of this control
	 */
	public Event getEvent() {
		return this.event;
	}
	
	/**
	 * @param event new event
	 */
	public void setEvent(final Event event) {
		this.event = event;
		
		if (event == null) {
			this.subjectText.setText("");
			this.descriptionText.setText("");
			this.placeText.setText("");
			
			this.beginDateTime.setCalendar(new GregorianCalendar());
			this.endDateTime.setCalendar(new GregorianCalendar());
			this.allDayButton.setSelection(false);
			this.statusCombo.setText("BUSY");
			this.repeatingEventCheckbox.setSelection(false);
			this.patternComposite.setVisible(false);
			this.patternComposite.setPattern(null);
		} else {
			this.subjectText.setText(event.getSubject());
			this.descriptionText.setText(event.getDescription());
			this.placeText.setText(event.getPlace());
			
			this.beginDateTime.setCalendar(event.getBegin());
			this.endDateTime.setCalendar(event.getEnd());
			this.allDayButton.setSelection(event.getAllDay());
			this.statusCombo.setText(event.getStatus().toString());
			
			if (event instanceof RepeatingEvent) {
				this.repeatingEventCheckbox.setSelection(true);
				this.patternComposite.setVisible(true);
				RepeatingEvent re = (RepeatingEvent) event;
				this.patternComposite.setPattern(re.getEventPattern());
			} else {
				this.repeatingEventCheckbox.setSelection(false);
				this.patternComposite.setVisible(false);
			}
		}
	}
	
	/**
	 * @return verification
	 */
	public boolean verify() {
		String msg = this.getVerificationMessage();
		this.outputLabel.setText(msg);
		return msg.trim().equals("");
	}
	
	/**
	 * @return verification-message
	 */
	public String getVerificationMessage() {
		boolean datevalid = this.endDateTime.verify(this.beginDateTime.getCalendar());
		String errorMessage = "";
		if (!datevalid) {
			errorMessage = errorMessage.concat("End is not later than begin.\n");
		}
		if (this.repeatingEventCheckbox.getSelection()) {
			errorMessage = errorMessage.concat(patternComposite.getVerificationMessage());
		}
		if (this.subjectText.getText().trim().equals("")) {
			errorMessage = errorMessage.concat("You have to enter a Subject!");
		}
		return errorMessage;
	}
	
	/**
	 * @return parsed Event
	 */
	public Event parseEvent() {
		if (this.repeatingEventCheckbox.getSelection()) {
			return new RepeatingEvent(this.subjectText.getText(), 
					this.placeText.getText(),
					this.allDayButton.getSelection(),
					this.descriptionText.getText(),
					StatusEnum.valueOf(this.statusCombo.getText()),
					this.beginDateTime.getCalendar(),
					this.endDateTime.getCalendar(),
					this.patternComposite.getPattern());
		} else {
			return new SingleEvent(this.subjectText.getText(), 
					this.placeText.getText(),
					this.allDayButton.getSelection(),
					this.descriptionText.getText(),
					StatusEnum.valueOf(this.statusCombo.getText()),
					this.beginDateTime.getCalendar(),
					this.endDateTime.getCalendar());
		}
	}
	/**
	 * 
	 */
	public void startEditMode() {
		editButton.setEnabled(false);
		subjectText.setEditable(true);
		descriptionText.setEditable(true);
		placeText.setEditable(true);
		beginDateTime.setEnabled(true);
		endDateTime.setEnabled(true);
		statusCombo.setEnabled(true);
		allDayButton.setEnabled(true);
		repeatingEventCheckbox.setEnabled(true);
		patternComposite.setEnabled(true);
		if (allDayButton.getSelection()) {
			beginDateTime.setTimeEnabled(false);
			endDateTime.setTimeEnabled(false);
		}
		confirmButton.setVisible(true);
		cancelButton.setVisible(true);
	}
	/**
	 * 
	 */
	public void endEditMode() {
		setEvent(event);
		subjectText.setEditable(false);
		descriptionText.setEditable(false);
		placeText.setEditable(false);
		beginDateTime.setEnabled(false);
		endDateTime.setEnabled(false);
		statusCombo.setEnabled(false);
		allDayButton.setEnabled(false);
		repeatingEventCheckbox.setEnabled(false);
		patternComposite.setEnabled(false);
		
		confirmButton.setVisible(false);
		cancelButton.setVisible(false);
		editButton.setEnabled(true);
	}

}
